#!/usr/bin/env python3
"""
邮件消息管理路由
提供邮件的CRUD操作、发送、批量处理等功能
"""

from flask import Blueprint, request, jsonify
from werkzeug.utils import secure_filename
from flask_jwt_extended import jwt_required, get_jwt_identity
from datetime import datetime
import json
import logging
import smtplib
import imaplib
import requests
import os
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
from email.header import Header
from email.utils import formatdate, make_msgid

from models import db, EmailAccount, EmailMessage
from utils.encryption import email_encryption
from services.email_service import EmailService

email_logger = logging.getLogger('email_system')

# 创建蓝图
messages_bp = Blueprint('email_messages', __name__)


@messages_bp.route('/', methods=['GET'])
@jwt_required()
def get_email_messages():
    """获取邮件列表"""
    try:
        current_user_id = int(get_jwt_identity())
        
        # 获取查询参数
        folder = request.args.get('folder', 'inbox')
        is_read = request.args.get('is_read')
        account_id = request.args.get('account_id')
        search = request.args.get('search', '')
        page = int(request.args.get('page', 1))
        per_page = int(request.args.get('per_page', 20))
        
        # 标准化文件夹名称 - 保持完整路径
        # 将所有标准文件夹名转换为小写，但保留自定义文件夹的原始大小写
        if folder.lower() in ['inbox', 'sent', 'drafts', 'trash', 'junk']:
            normalized_folder = folder.lower()
        else:
            # 自定义文件夹保持原样
            normalized_folder = folder
        
        # 移除开头的斜杠
        if normalized_folder.startswith('/'):
            normalized_folder = normalized_folder[1:]
        
        email_logger.info(f"[邮件查询] 原始: {folder}, 标准化: {normalized_folder}, 账号: {account_id}")
        
        # 构建查询
        query = EmailMessage.query.filter_by(user_id=current_user_id)
        
        if folder:
            query = query.filter_by(folder=normalized_folder)
        
        if is_read is not None:
            query = query.filter_by(is_read=is_read.lower() == 'true')
        
        if account_id:
            query = query.filter_by(email_account_id=account_id)
        
        if search:
            # 使用ILIKE提高性能(PostgreSQL)或考虑全文搜索
            search_pattern = f"%{search}%"
            query = query.filter(
                db.or_(
                    EmailMessage.subject.ilike(search_pattern),
                    EmailMessage.sender.ilike(search_pattern),
                    # 正文搜索可选,避免性能问题
                    # EmailMessage.body_text.ilike(search_pattern)
                )
            )
        
        # 分页
        messages = query.order_by(EmailMessage.received_at.desc()).paginate(
            page=page, per_page=per_page, error_out=False
        )
        
        return jsonify({
            'messages': [message.to_dict() for message in messages.items],
            'pagination': {
                'page': page,
                'per_page': per_page,
                'total': messages.total,
                'pages': messages.pages,
                'has_next': messages.has_next,
                'has_prev': messages.has_prev
            }
        }), 200
        
    except Exception as e:
        return jsonify({'error': str(e)}), 500


@messages_bp.route('/<int:message_id>', methods=['GET'])
@jwt_required()
def get_email_message(message_id):
    """获取邮件详情"""
    try:
        current_user_id = int(get_jwt_identity())
        message = EmailMessage.query.filter_by(id=message_id, user_id=current_user_id).first()
        
        if not message:
            return jsonify({'error': '邮件不存在'}), 404
        
        return jsonify({
            'message': message.to_dict()
        }), 200
        
    except Exception as e:
        return jsonify({'error': str(e)}), 500


@messages_bp.route('/<int:message_id>', methods=['PUT'])
@jwt_required()
def update_email_message(message_id):
    """更新邮件状态"""
    try:
        current_user_id = int(get_jwt_identity())
        message = EmailMessage.query.filter_by(id=message_id, user_id=current_user_id).first()
        
        if not message:
            return jsonify({'error': '邮件不存在'}), 404
        
        data = request.get_json()
        
        # 更新字段
        if 'is_read' in data:
            message.is_read = data['is_read']
        if 'is_starred' in data:
            message.is_starred = data['is_starred']
        if 'folder' in data:
            message.folder = data['folder']
        if 'ai_summary' in data:
            message.ai_summary = data['ai_summary']
        
        db.session.commit()
        
        return jsonify({
            'success': True,
            'message': message.to_dict()
        }), 200
        
    except Exception as e:
        db.session.rollback()
        return jsonify({'error': str(e)}), 500


@messages_bp.route('/<int:message_id>', methods=['DELETE'])
@jwt_required()
def delete_email_message(message_id):
    """删除邮件"""
    try:
        current_user_id = int(get_jwt_identity())
        message = EmailMessage.query.filter_by(id=message_id, user_id=current_user_id).first()
        
        if not message:
            return jsonify({'error': '邮件不存在'}), 404
        
        db.session.delete(message)
        db.session.commit()
        
        return jsonify({
            'success': True,
            'message': '邮件已删除'
        }), 200
        
    except Exception as e:
        db.session.rollback()
        return jsonify({'error': str(e)}), 500


@messages_bp.route('/send', methods=['POST'])
@jwt_required()
def send_email():
    """发送邮件 - 支持HTML、附件和完整邮件头"""
    smtp_server = None
    try:
        current_user_id = int(get_jwt_identity())
        
        # 支持 JSON 和 FormData 两种格式
        if request.is_json:
            data = request.get_json()
            files = []
        else:
            data = request.form.to_dict()
            files = request.files.getlist('attachments')
        
        # 验证必填字段
        required_fields = ['account_id', 'to', 'subject', 'body']
        for field in required_fields:
            if not data or not data.get(field):
                return jsonify({'error': f'{field} 不能为空'}), 400
        
        # 获取邮箱账号
        account = EmailAccount.query.filter_by(id=data['account_id'], user_id=current_user_id).first()
        if not account:
            return jsonify({'error': '邮箱配置不存在'}), 404
        
        # 解密密码
        password = email_encryption.decrypt_password(account.password)
        
        # 解析收件人、抄送、密送
        to_list = [addr.strip() for addr in data['to'].split(',') if addr.strip()]
        cc_list = [addr.strip() for addr in data.get('cc', '').split(',') if addr.strip()]
        bcc_list = [addr.strip() for addr in data.get('bcc', '').split(',') if addr.strip()]
        
        if not to_list:
            return jsonify({'error': '收件人不能为空'}), 400
        
        # 获取邮件内容
        subject = data['subject']
        body_text = data['body']
        body_html = data.get('body_html', '')
        
        # 创建邮件对象
        # 如果有HTML内容或附件，使用 multipart/mixed
        if body_html or files:
            msg = MIMEMultipart('mixed')
            
            # 如果同时有纯文本和HTML，创建 alternative 部分
            if body_html:
                msg_alternative = MIMEMultipart('alternative')
                msg_alternative.attach(MIMEText(body_text, 'plain', 'utf-8'))
                msg_alternative.attach(MIMEText(body_html, 'html', 'utf-8'))
                msg.attach(msg_alternative)
            else:
                msg.attach(MIMEText(body_text, 'plain', 'utf-8'))
        else:
            msg = MIMEMultipart()
            msg.attach(MIMEText(body_text, 'plain', 'utf-8'))
        
        # 设置邮件头部
        msg['From'] = Header(account.name, 'utf-8').encode() + f' <{account.email}>' if account.name else account.email
        msg['To'] = ', '.join(to_list)
        if cc_list:
            msg['Cc'] = ', '.join(cc_list)
        # 注意：BCC不应该出现在邮件头中
        msg['Subject'] = Header(subject, 'utf-8').encode()
        
        # 添加标准邮件头部
        msg['Date'] = formatdate(localtime=True)
        message_id = make_msgid(domain=account.email.split('@')[1] if '@' in account.email else 'localhost')
        msg['Message-ID'] = message_id
        msg['X-Mailer'] = 'Feng Admin Mail Client v1.0'
        
        # 处理附件
        attachments_info = []
        for file in files:
            if file and file.filename:
                filename = secure_filename(file.filename)
                file_data = file.read()
                
                # 创建附件部分
                part = MIMEBase('application', 'octet-stream')
                part.set_payload(file_data)
                encoders.encode_base64(part)
                
                # 使用 RFC 2231 编码文件名以支持中文
                part.add_header(
                    'Content-Disposition',
                    'attachment',
                    filename=('utf-8', '', filename)
                )
                msg.attach(part)
                
                # 记录附件信息
                attachments_info.append({
                    'filename': filename,
                    'size': len(file_data)
                })
                
                email_logger.info(f"[发送邮件] 添加附件: {filename}, 大小: {len(file_data)} 字节")
        
        # 发送邮件
        email_logger.info(f"[发送邮件] 开始发送 - 发件人: {account.email}, 收件人: {to_list}")
        
        # QQ邮箱端口587使用STARTTLS，端口465使用SSL
        if account.smtp_port == 465:
            smtp_server = smtplib.SMTP_SSL(account.smtp_server, account.smtp_port, timeout=30)
        else:
            smtp_server = smtplib.SMTP(account.smtp_server, account.smtp_port, timeout=30)
            smtp_server.starttls()
        
        smtp_server.login(account.username, password)
        
        # 发送邮件（包括BCC）
        all_recipients = to_list + cc_list + bcc_list
        smtp_server.send_message(msg, to_addrs=all_recipients)
        smtp_server.quit()
        smtp_server = None
        
        email_logger.info(f"[发送邮件] 发送成功 - Message-ID: {message_id}")
        
        # 保存到数据库的已发送文件夹
        try:
            sent_message = EmailMessage(
                user_id=current_user_id,
                email_account_id=account.id,
                message_id=message_id,
                subject=subject,
                sender=account.email,
                recipients=json.dumps(to_list),
                cc=json.dumps(cc_list) if cc_list else '[]',
                body_text=body_text,
                body_html=body_html if body_html else '',
                attachments=json.dumps(attachments_info),
                is_read=True,
                is_full_content=True,
                folder='sent',
                imap_folder='Sent',
                received_at=datetime.utcnow(),
                content_size=len(msg.as_string())
            )
            db.session.add(sent_message)
            db.session.commit()
            
            email_logger.info(f"[发送邮件] 已保存到数据库 - ID: {sent_message.id}")
            
            return jsonify({
                'success': True,
                'message': '邮件发送成功',
                'message_id': message_id,
                'saved_to_db': True
            }), 200
            
        except Exception as db_error:
            email_logger.error(f"[发送邮件] 保存到数据库失败: {db_error}")
            # 即使保存失败，邮件已经发送成功
            return jsonify({
                'success': True,
                'message': '邮件发送成功（但未保存到本地）',
                'message_id': message_id,
                'saved_to_db': False,
                'db_error': str(db_error)
            }), 200
        
    except smtplib.SMTPAuthenticationError as e:
        email_logger.error(f"[发送邮件] SMTP认证失败: {e}")
        return jsonify({'error': 'SMTP认证失败，请检查用户名和密码'}), 401
    except smtplib.SMTPException as e:
        email_logger.error(f"[发送邮件] SMTP错误: {e}")
        return jsonify({'error': f'邮件发送失败: {str(e)}'}), 500
    except Exception as e:
        email_logger.error(f"[发送邮件] 未知错误: {e}")
        import traceback
        traceback.print_exc()
        return jsonify({'error': f'发送失败: {str(e)}'}), 500
    finally:
        # 确保关闭SMTP连接
        if smtp_server:
            try:
                smtp_server.quit()
            except:
                pass


@messages_bp.route('/batch', methods=['POST'])
@jwt_required()
def batch_update_messages():
    """批量操作邮件"""
    try:
        current_user_id = int(get_jwt_identity())
        data = request.get_json()
        
        message_ids = data.get('message_ids', [])
        action = data.get('action')
        
        if not message_ids or not action:
            return jsonify({'error': '缺少必要参数'}), 400
        
        # 获取邮件
        messages = EmailMessage.query.filter(
            EmailMessage.id.in_(message_ids),
            EmailMessage.user_id == current_user_id
        ).all()
        
        if not messages:
            return jsonify({'error': '没有找到邮件'}), 404
        
        # 执行批量操作
        updated_count = 0
        
        if action == 'mark_read':
            for message in messages:
                message.is_read = True
                updated_count += 1
        elif action == 'mark_unread':
            for message in messages:
                message.is_read = False
                updated_count += 1
        elif action == 'star':
            for message in messages:
                message.is_starred = True
                updated_count += 1
        elif action == 'unstar':
            for message in messages:
                message.is_starred = False
                updated_count += 1
        elif action == 'delete':
            for message in messages:
                db.session.delete(message)
                updated_count += 1
        elif action == 'move_to_trash':
            for message in messages:
                message.folder = 'trash'
                updated_count += 1
        
        db.session.commit()
        
        return jsonify({
            'success': True,
            'message': f'成功处理 {updated_count} 封邮件'
        }), 200
        
    except Exception as e:
        db.session.rollback()
        return jsonify({'error': str(e)}), 500


@messages_bp.route('/<int:message_id>/load-body', methods=['POST'])
@jwt_required()
def load_message_body(message_id):
    """按需加载邮件正文"""
    try:
        current_user_id = int(get_jwt_identity())
        
        # 查找邮件记录
        message = EmailMessage.query.filter_by(id=message_id, user_id=current_user_id).first()
        if not message:
            return jsonify({'error': '邮件不存在'}), 404
        
        # 调用服务层加载函数
        result = EmailService.fetch_full_email_body(message.email_account_id, message_id)
        
        if result['success']:
            return jsonify({
                'success': True,
                'message': result['message']
            }), 200
        else:
            return jsonify({'error': result['error']}), 400
        
    except Exception as e:
        return jsonify({'error': str(e)}), 500


@messages_bp.route('/load-more-history', methods=['POST'])
@jwt_required()
def load_more_history():
    """加载更早的邮件头部"""
    try:
        current_user_id = int(get_jwt_identity())
        data = request.get_json()
        
        account_id = data.get('account_id')
        folder = data.get('folder', 'inbox')
        before_uid = data.get('before_uid')  # 可选，用于分页
        
        if not account_id:
            return jsonify({'error': '缺少account_id参数'}), 400
        
        # 验证邮箱账号
        account = EmailAccount.query.filter_by(id=account_id, user_id=current_user_id).first()
        if not account:
            return jsonify({'error': '邮箱账号不存在'}), 404
        
        # 解密密码
        password = email_encryption.decrypt_password(account.password)
        
        # 连接IMAP服务器
        if account.use_ssl:
            mail = imaplib.IMAP4_SSL(account.imap_server, account.imap_port)
        else:
            mail = imaplib.IMAP4(account.imap_server, account.imap_port)
        
        mail.login(account.username, password)
        
        # Determine imap_folder_name from existing message or use folder as fallback
        existing_msg = EmailMessage.query.filter_by(
            email_account_id=account_id,
            folder=folder
        ).first()
        
        imap_folder_name = existing_msg.imap_folder if existing_msg and existing_msg.imap_folder else folder
        
        # 选择文件夹
        status, count = mail.select(imap_folder_name)
        if status != 'OK':
            mail.close()
            mail.logout()
            return jsonify({'error': f'无法选择文件夹 {imap_folder_name}'}), 400
        
        # 获取更早的邮件
        from config import Config
        
        if before_uid:
            # 使用UID搜索比before_uid更早的邮件
            status, messages = mail.search(None, f'UID 1:{before_uid-1}')
        else:
            # 获取所有邮件
            status, messages = mail.search(None, 'ALL')
        
        if status != 'OK' or not messages[0]:
            mail.close()
            mail.logout()
            return jsonify({'messages': [], 'has_more': False}), 200
        
        email_ids = messages[0].split()
        
        # 只取最新的N封（历史邮件批次大小）
        if len(email_ids) > Config.EMAIL_HISTORY_BATCH_SIZE:
            email_ids = email_ids[-Config.EMAIL_HISTORY_BATCH_SIZE:]
        
        # 仅拉取邮件头部
        headers_list = EmailService.fetch_headers_only(mail, email_ids, account, folder, imap_folder_name)
        
        # 批量插入数据库
        new_messages = []
        for header_data in headers_list:
            existing_message = EmailMessage.query.filter_by(
                user_id=header_data['user_id'],
                message_id=header_data['message_id']
            ).first()
            if not existing_message:
                message = EmailMessage(**header_data)
                db.session.add(message)
                new_messages.append(message.to_dict())
        
        db.session.commit()
        
        mail.close()
        mail.logout()
        
        # 判断是否还有更多邮件
        has_more = len(email_ids) == Config.EMAIL_HISTORY_BATCH_SIZE
        
        return jsonify({
            'success': True,
            'messages': new_messages,
            'has_more': has_more,
            'count': len(new_messages)
        }), 200
        
    except Exception as e:
        db.session.rollback()
        return jsonify({'error': str(e)}), 500

